package demoMod.invincibleOne.characters;

import basemod.abstracts.CustomPlayer;
import basemod.animations.G3DJAnimation;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.math.MathUtils;
import com.esotericsoftware.spine.AnimationState;
import com.megacrit.cardcrawl.actions.AbstractGameAction;
import com.megacrit.cardcrawl.actions.common.GainBlockAction;
import com.megacrit.cardcrawl.actions.common.RelicAboveCreatureAction;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.cards.DamageInfo;
import com.megacrit.cardcrawl.characters.AbstractPlayer;
import com.megacrit.cardcrawl.core.CardCrawlGame;
import com.megacrit.cardcrawl.core.EnergyManager;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.events.city.Vampires;
import com.megacrit.cardcrawl.helpers.FontHelper;
import com.megacrit.cardcrawl.helpers.ImageMaster;
import com.megacrit.cardcrawl.helpers.ModHelper;
import com.megacrit.cardcrawl.localization.CharacterStrings;
import com.megacrit.cardcrawl.monsters.AbstractMonster;
import com.megacrit.cardcrawl.relics.MarkOfTheBloom;
import com.megacrit.cardcrawl.rooms.AbstractRoom;
import com.megacrit.cardcrawl.rooms.EventRoom;
import com.megacrit.cardcrawl.screens.CharSelectInfo;
import com.megacrit.cardcrawl.ui.panels.energyorb.EnergyOrbRed;
import com.megacrit.cardcrawl.vfx.UpgradeShineEffect;
import com.megacrit.cardcrawl.vfx.combat.HealEffect;
import com.megacrit.cardcrawl.core.Settings;
import demoMod.invincibleOne.InvincibleOneMod;
import demoMod.invincibleOne.actions.AutoPlayCardAction;
import demoMod.invincibleOne.cards.invincible.*;
import demoMod.invincibleOne.effects.EndCGEffect;
import demoMod.invincibleOne.enums.AbstractCardEnum;
import demoMod.invincibleOne.enums.AbstractPlayerEnum;
import demoMod.invincibleOne.relics.SecondWindRelic;
import demoMod.invincibleOne.relics.TaskGoal;
import demoMod.invincibleOne.skins.*;

import java.util.*;

import static com.megacrit.cardcrawl.core.CardCrawlGame.languagePack;

public class InvincibleOne extends CustomPlayer {
    private static final CharacterStrings charStrings;
    public static final String NAME;
    public static final String DESCRIPTION;
    // 给其他mod暴露
    public static ArrayList<Skin> registerSkins = new ArrayList<>();

    public InvincibleOne(String name, PlayerClass setClass) {
        super(name, setClass, new EnergyOrbRed(), new G3DJAnimation(null, null));

        Skin.skins = new ArrayList<>();
        Skin.skins.add(new OriginalSkin());
        Skin.skins.add(new BaiXiSkin());
        Skin.skins.add(new PrimeSkin());
        Skin.skins.add(new TheDefect());
        Skin.skins.add(new YangJian());
        Skin.skins.add(new TheWatcher());
        Skin.skins.addAll(registerSkins);
        for (Skin sk : Skin.skins) {
            sk.load();
        }

        this.dialogX = this.drawX + 150.0F * Settings.scale;
        this.dialogY = this.drawY + 250.0F * Settings.scale;

        this.initializeClass(InvincibleOneMod.getResourcePath("char/character1.png"), InvincibleOneMod.getResourcePath("char/shoulder1_2.png"),
                InvincibleOneMod.getResourcePath("char/shoulder1_1.png"), InvincibleOneMod.getResourcePath("char/corpse.png"), this.getLoadout(),
                0.0F, -20F, 250.0F, 270.0F, new EnergyManager(3));
        if (ModHelper.enabledMods.size() > 0 && (ModHelper.isModEnabled("Diverse") || ModHelper.isModEnabled("Chimera") || ModHelper.isModEnabled("Blue Cards"))) {
            this.masterMaxOrbs = 1;
        }
        Skin sk = Skin.skinNow();
        this.corpseImg = sk.sprite;
        if (!sk.atlasPath.isEmpty()) {
            this.img = null;
             this.loadAnimation(InvincibleOneMod.getResourcePath("char/" + sk.atlasPath + ".atlas"),
                     InvincibleOneMod.getResourcePath("char/" + sk.atlasPath + "37.json"), sk.atlasScale);
             AnimationState.TrackEntry e = this.state.setAnimation(0, sk.atlasIdle, true);
             e.setTime(e.getEndTime() * MathUtils.random());
             e.setTimeScale(1.2F);
        } else {
            this.img = sk.sprite;
            this.atlas = null;
        }
        this.shoulderImg = sk.shoulder1;
        this.shoulder2Img = sk.shoulder2;
        EndCGEffect.cgs = sk.deathCG;

        Skin.TrashTalkGameStart1 = languagePack.getUIString(sk.trashTalkPrefix + "GameStart1").TEXT;
        Skin.TrashTalkGameStart2 = languagePack.getUIString(sk.trashTalkPrefix + "GameStart2").TEXT;
        Skin.TrashTalkGameStart3 = languagePack.getUIString(sk.trashTalkPrefix + "GameStart3").TEXT;
        Skin.TrashTalkGameStart4 = languagePack.getUIString(sk.trashTalkPrefix + "GameStart4").TEXT;
        Skin.TrashTalkGameStart5 = languagePack.getUIString(sk.trashTalkPrefix + "GameStart5").TEXT;
        Skin.TrashTalkAct2_1 = languagePack.getUIString(sk.trashTalkPrefix + "Act2_1").TEXT;
        Skin.TrashTalkAct2_2 = languagePack.getUIString(sk.trashTalkPrefix + "Act2_2").TEXT;
        Skin.TrashTalkAct3 = languagePack.getUIString(sk.trashTalkPrefix + "Act3").TEXT;
        Skin.TrashTalkFightTheHeart = languagePack.getUIString(sk.trashTalkPrefix + "FightTheHeart").TEXT;
        Skin.TrashTalkFightTheHeartProvoked = languagePack.getUIString(sk.trashTalkPrefix + "FightTheHeartProvoked").TEXT;
        Skin.TrashTalkDamage5 = languagePack.getUIString(sk.trashTalkPrefix + "Damage5").TEXT;
        Skin.TrashTalkDamage5Provoked = languagePack.getUIString(sk.trashTalkPrefix + "Damage5Provoked").TEXT;
        Skin.TrashTalkDamage15 = languagePack.getUIString(sk.trashTalkPrefix + "Damage15").TEXT;
        Skin.TrashTalkSecondWind = languagePack.getUIString(sk.trashTalkPrefix + "SecondWind").TEXT;
        Skin.TrashTalkSecondWindProvoked = languagePack.getUIString(sk.trashTalkPrefix + "SecondWindProvoked").TEXT;
        Skin.TrashTalkKillAll = languagePack.getUIString(sk.trashTalkPrefix + "KillAll").TEXT;
    }

    @Override
    public void damage(DamageInfo info) {
        if (AbstractDungeon.getCurrRoom() instanceof EventRoom && AbstractDungeon.getCurrRoom().phase != AbstractRoom.RoomPhase.COMBAT && InvincibleOneMod.seriousLevel[CardCrawlGame.saveSlot] >= 5) {
            info.output = 0;
        }
        super.damage(info);
        if (isDead && hasRelic(SecondWindRelic.ID) && getRelic(SecondWindRelic.ID).counter > 0) {
            isDead = false;
            getRelic(SecondWindRelic.ID).flash();
            getRelic(SecondWindRelic.ID).counter--;
            if (getRelic(SecondWindRelic.ID).counter == 0) {
                getRelic(SecondWindRelic.ID).beginLongPulse();
            }
            currentHealth = (int) (maxHealth * Skin.skinNow().onReborn());
            healthBarRevivedEvent();
            AbstractDungeon.topPanel.panelHealEffect();
            AbstractDungeon.effectsQueue.add(new HealEffect(hb.cX - animX, hb.cY, (int) (maxHealth * 0.3F)));
            if (AbstractDungeon.getCurrRoom().phase == AbstractRoom.RoomPhase.COMBAT) {
                AbstractDungeon.actionManager.addToBottom(new AbstractGameAction() {
                    @Override
                    public void update() {
                        drawPile.group.forEach(c -> {
                            if (c.rarity == AbstractCard.CardRarity.BASIC && c.canUpgrade()) {
                                c.upgrade();
                            }
                        });
                        hand.group.forEach(c -> {
                            if (c.rarity == AbstractCard.CardRarity.BASIC && c.canUpgrade()) {
                                c.upgrade();
                            }
                        });
                        discardPile.group.forEach(c -> {
                            if (c.rarity == AbstractCard.CardRarity.BASIC && c.canUpgrade()) {
                                c.upgrade();
                            }
                        });
                        exhaustPile.group.forEach(c -> {
                            if (c.rarity == AbstractCard.CardRarity.BASIC && c.canUpgrade()) {
                                c.upgrade();
                            }
                        });
                        limbo.group.forEach(c -> {
                            if (c.rarity == AbstractCard.CardRarity.BASIC && c.canUpgrade()) {
                                c.upgrade();
                            }
                        });
                        masterDeck.group.forEach(c -> {
                            if (c.rarity == AbstractCard.CardRarity.BASIC && c.canUpgrade()) {
                                c.upgrade();
                            }
                        });
                        isDone = true;
                    }
                });
                AbstractDungeon.actionManager.addToBottom(new RelicAboveCreatureAction(this, getRelic(SecondWindRelic.ID)));
                AbstractDungeon.actionManager.addToTop(new GainBlockAction(this, this, 75));

                // 垃圾话
                List<String> collection;
                if (InvincibleOneMod.provoked[CardCrawlGame.saveSlot]) {
                    collection = Arrays.asList(Skin.TrashTalkSecondWindProvoked);
                } else {
                    collection = Arrays.asList(Skin.TrashTalkSecondWind);
                }
                Collections.shuffle(collection, new Random(AbstractDungeon.shuffleRng.randomLong()));
                Skin.TrashTalk(collection.get(0), true);
            } else {
                AbstractDungeon.effectsQueue.add(new UpgradeShineEffect(Settings.WIDTH / 2.0F, Settings.HEIGHT / 2.0F));
                for (AbstractCard c: AbstractDungeon.player.masterDeck.group) {
                    if (c.rarity == AbstractCard.CardRarity.BASIC) {
                        c.upgrade();
                    }
                }
            }
        }
    }

    @Override
    public void applyStartOfTurnPostDrawRelics() {
        super.applyStartOfTurnPostDrawRelics();
        AbstractDungeon.overlayMenu.endTurnButton.enabled = false;
        AbstractDungeon.actionManager.addToBottom(new AbstractGameAction() {
            @Override
            public void update() {
                AbstractDungeon.actionManager.addToBottom(new AutoPlayCardAction());
                isDone = true;
            }
        });
    }

    @Override
    public void useCard(AbstractCard c, AbstractMonster monster, int energyOnUse) {
        super.useCard(c, monster, energyOnUse);
        AbstractDungeon.actionManager.addToBottom(new AbstractGameAction() {
            @Override
            public void update() {
                if (!AbstractDungeon.overlayMenu.endTurnButton.enabled) {
                    isDone = true;
                    return;
                }
                AbstractDungeon.actionManager.addToBottom(new AutoPlayCardAction());
                isDone = true;
            }
        });
    }

    @Override
    public ArrayList<String> getStartingDeck() {
        return Skin.skinNow().getStartingDeck();
    }

    @Override
    public Texture getEnergyImage() {
        return ImageMaster.ENERGY_RED_LAYER1;
    }

    @Override
    public ArrayList<String> getStartingRelics() {
        ArrayList<String> ret = new ArrayList<>();
        ret.add(TaskGoal.ID);
        ret.add(MarkOfTheBloom.ID);
        return ret;
    }

    @Override
    public CharSelectInfo getLoadout() {
        return new CharSelectInfo(NAME, DESCRIPTION, 140, 140, 0, 99, 5, this,
                getStartingRelics(), getStartingDeck(), false);
    }

    @Override
    public String getTitle(PlayerClass playerClass) {
        return NAME;
    }

    @Override
    public AbstractCard.CardColor getCardColor() {
        return AbstractCardEnum.INVINCIBLE;
    }

    @Override
    public Color getCardRenderColor() {
        return InvincibleOneMod.mainInvColor;
    }

    @Override
    public AbstractCard getStartCardForEvent() {
        return new OutOfThinAir();
    }

    @Override
    public Color getCardTrailColor() {
        return InvincibleOneMod.mainInvColor.cpy();
    }

    @Override
    public int getAscensionMaxHPLoss() {
        return 9;
    }

    @Override
    public BitmapFont getEnergyNumFont() {
        return FontHelper.energyNumFontRed;
    }

    @Override
    public void doCharSelectScreenSelectEffect() {

    }

    @Override
    public String getCustomModeCharacterButtonSoundKey() {
        return "ATTACK_HEAVY";
    }

    @Override
    public String getLocalizedCharacterName() {
        return NAME;
    }

    @Override
    public AbstractPlayer newInstance() {
        return new InvincibleOne("InvincibleOne", AbstractPlayerEnum.INVINCIBLE);
    }

    @Override
    public String getSpireHeartText() {
        return "";
    }

    @Override
    public Color getSlashAttackColor() {
        return Color.RED;
    }

    @Override
    public AbstractGameAction.AttackEffect[] getSpireHeartSlashEffect() {
        return new AbstractGameAction.AttackEffect[]{
                AbstractGameAction.AttackEffect.BLUNT_LIGHT,
                AbstractGameAction.AttackEffect.BLUNT_LIGHT,
                AbstractGameAction.AttackEffect.BLUNT_LIGHT,
                AbstractGameAction.AttackEffect.BLUNT_HEAVY,
                AbstractGameAction.AttackEffect.BLUNT_HEAVY,
                AbstractGameAction.AttackEffect.BLUNT_HEAVY,
                AbstractGameAction.AttackEffect.BLUNT_HEAVY
        };
    }

    @Override
    public String getVampireText() {
        return Vampires.DESCRIPTIONS[1];
    }

    static {
        charStrings = CardCrawlGame.languagePack.getCharacterString("InvincibleOne");
        NAME = charStrings.NAMES[0];
        DESCRIPTION = charStrings.TEXT[0];
    }
}
